Мы попытаемся найти зависимости продаж между регионами.
Для этого нужно сравнить различные комбинации продаж в регионах и найти наиболее коррелируемые. После этого попробовать различные модели и при необходимости выполнить их настройку.
Для начала импортируем данные и выполним первичный анализ.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline
import seaborn as sns
sns.set_style('dark')
df = pd.read_csv('vgsales.csv')
df.head()
Датасет содержит список игр с продажами более 100 000 копий. Данные взяты с сайта vgchartz.com.
Rank - Ranking of overall sales
Name - название игры
Platform - платформа (т.е. PC,PS4, итд.)
Year - год выпуска
Genre - жанр
Publisher - издатель
NA_Sales - продажи в Северной Америке (в миллионах)
EU_Sales - продажи в Европе (в миллионах)
JP_Sales - продажи в Японии (в миллионах)
Other_Sales - продажи в остальных странах (в миллионах)
Global_Sales - суммарная продажа со всех стран
Посмотрим информацию о фичах.
df.info()
df.describe()
Данные довольно полные, это избавляет нас от надобности чистить их.
Выведем количество игр относительно платформ
df['Platform'].value_counts()
Выведем количество игр относительно жанров
df['Genre'].value_counts()
Для улучшения анализа и визуализации избавимся от игр с издателями, которые опубликовали менее 50 игр и платформ с менее чем 90 играми. Издатели с менее чем 50 играми и платформы с меньше чем 90 играми будут переименованы в "Other".
for i in df['Publisher'].unique():
if df['Publisher'][df['Publisher'] == i].count() < 50:
df['Publisher'][df['Publisher'] == i] = 'Other'
for i in df['Platform'].unique():
if df['Platform'][df['Platform'] == i].count() < 90:
df['Platform'][df['Platform'] == i] = 'Other'
Посмотрим что поменялось
df['Publisher'].value_counts()
df['Platform'].value_counts()
Теперь после очистки построим графики
df['Publisher'].value_counts(sort=True).plot(kind='barh',figsize=(16,16))
df['Platform'].value_counts(sort=True).plot(kind='barh',figsize=(16,16))
Построим график по жанрам
sns.factorplot('Genre',data=df,kind='count',size=16)
Выведем количество игр имеющих более 1 миллиона копий, проданных в Свереной Америке и сгруппируем их по платформам
df.index.name = 'Index'
platform_name = []
platform_frequency = []
for i in df['Platform'].unique():
platform_name.append(i)
platform_frequency.append(df['Name'][df['NA_Sales'] > 1.0][df['Platform'] == i].count())
plat = pd.DataFrame()
plat["Name"] = platform_name
plat["Frequency"] = platform_frequency
plat
С помощью полученного выше датафрейма можем построить круговую диаграмму.
plat.plot(kind='pie',y='Frequency',labels=plat['Name'],legend=False,figsize=(16,16))
Посмотрим корелляцию между регионами
corr_1 = []
corr_2 = []
corr_res = []
sales_list = ['NA_Sales','EU_Sales','JP_Sales','Other_Sales','Global_Sales']
for i in sales_list:
for j in sales_list:
corr_1.append(i)
corr_2.append(j)
corr_res.append(df[i].corr(df[j]))
corr_data = pd.DataFrame(
{'Corr_1': corr_1,
'Corr_2': corr_2,
'Correlation': corr_res
})
corr_data = corr_data.pivot(values='Correlation',index='Corr_1',columns='Corr_2')
corr_data
plt.figure(figsize = (12,10))
sns.heatmap(corr_data)
Заметим высокую корреляцию продаж в Северной Америке и глобальные продажи.
sns.jointplot(x="NA_Sales", y="Global_Sales", data=df, kind='reg')
from sklearn.model_selection import train_test_split
X = df.iloc[:, 6].values
y = df.iloc[:, 10].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 1/10, random_state = 0)
X_train = X_train.reshape((X_train.shape[0],1))
y_train = y_train.reshape((y_train.shape[0],1))
X_test = X_test.reshape((X_test.shape[0],1))
y_test = y_test.reshape((y_test.shape[0],1))
Импортируем регрессор из библиотеки sklearn. Обучимся на тестовой выборке.
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_test, y_test)
y_pred_test = regressor.predict(X_test)
y_pred_train = regressor.predict(X_train)
plt.figure(figsize = (16,16))
plt.scatter(X_train, y_train, color='green')
plt.plot(X_train, y_pred_train, color='blue')
plt.title('Train set')
plt.xlabel('North America Sales')
plt.ylabel('Global Sales')
plt.show()
plt.figure(figsize = (16,16))
plt.scatter(X_test, y_test, color='green')
plt.plot(X_test, y_pred_test, color='blue')
plt.title('Test set')
plt.xlabel('North America Sales')
plt.ylabel('Global Sales')
plt.show()
print("Training score: {:.2f}".format(regressor.score(X_train,y_train)))
print("Test score: {:.2f}".format(regressor.score(X_test,y_test)))
Линейный регрессор показал даволько хороший результат. Попробуем что то по интереснее, к примеру дерево решений.
from sklearn.tree import DecisionTreeRegressor
X = X.reshape((X.shape[0],1))
y = y.reshape((y.shape[0],1))
Dregressor = DecisionTreeRegressor(random_state=0)
Dregressor.fit(X,y)
y_pred = Dregressor.predict(X)
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.figure(figsize = (16,16))
plt.scatter(X, y, color = 'green')
plt.plot(X_grid, Dregressor.predict(X_grid), color = 'blue')
plt.title('Decision Tree Regression')
plt.xlabel('North America Sales')
plt.ylabel('Global Sales')
plt.show()
from sklearn.externals.six import StringIO
from IPython.display import Image
from sklearn.tree import export_graphviz
import pydotplus
dot_data = StringIO()
export_graphviz(Dregressor, out_file=dot_data,
filled=True, rounded=True,
special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
# дерево сохранено в файл dec_tree_games_max_depth.png
graph.write_png("dec_tree_games_max_depth.png")
Image(graph.create_png())
print("Decision tree score (max depth): {:.2f}".format(Dregressor.score(X,y)))
Дерево решений имеет лучший результат по сравнению с линейной регрессией. Однако оно получилось крайне широким, попробуем для лучшей визуализации уменьшить его глубину до 5 и посмотрим как изменится точность модели.
Dregressor = DecisionTreeRegressor(random_state=0, max_depth=5)
Dregressor.fit(X,y)
dot_data = StringIO()
export_graphviz(Dregressor, out_file=dot_data,
filled=True, rounded=True,
special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
# дерево сохранено в файл dec_tree_games_depth_5.png
graph.write_png("dec_tree_games_depth_5.png")
Image(graph.create_png())
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.figure(figsize = (16,16))
plt.scatter(X, y, color = 'green')
plt.plot(X_grid, Dregressor.predict(X_grid), color = 'blue')
plt.title('Decision Tree Regression')
plt.xlabel('North America Sales')
plt.ylabel('Global Sales')
plt.show()
print("Decision tree score (depth = 5): {:.2f}".format(Dregressor.score(X,y)))
Как можно заметить точность уменьшилась на 0.03%. За то дерево сильно уменьшилось, что может помочь не переобучиться и ускорить работу модели.
from sklearn.ensemble import RandomForestRegressor
Rregressor = RandomForestRegressor(n_estimators=300, random_state=0)
Rregressor.fit(X,y)
y_pred = Rregressor.predict(X)
X_grid = np.arange(min(X), max(X), 0.01)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.figure(figsize = (16,16))
plt.scatter(X, y, color = 'green')
plt.plot(X_grid, Rregressor.predict(X_grid), color = 'blue')
plt.title('(Random Forest Regression)')
plt.xlabel('North America Sales')
plt.ylabel('Global Sales')
plt.show()
print("Random Forest score: {:.2f}".format(Rregressor.score(X,y)))
Пока дерево решений все же показывает лучший результат.
Скорее всего метод покажет себя очень плохо, так как не очень подходит для наших целей.
from sklearn.svm import SVR
SVRregressor = SVR(kernel = 'rbf')
SVRregressor.fit(X,y)
Для нормальной работы алгоритма нужно произвести масштабирование фич.
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
sc_y = StandardScaler()
X = sc_X.fit_transform(X)
y = sc_y.fit_transform(y)
y_pred = sc_y.inverse_transform(SVRregressor.predict(sc_X.transform(X)))
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.figure(figsize = (16,16))
plt.scatter(X, y, color = 'green')
plt.plot(X_grid, SVRregressor.predict(X_grid), color = 'blue')
plt.title('(SVR)')
plt.xlabel('North America Sales')
plt.ylabel('Global Sales')
plt.show()
print("SVR score: {:.2f}".format(SVRregressor.score(X,y)))
Как и ожидалось, метод опорных векторов плохо себя показал.
Вывод: лучшей моделью для предсказания продаж оказалось дерево решений с неогранниченной глубиной, также неплохо себя показал случайный лес. Основываясь на продажах в Северной Америке мы можем с 95% вероятностью предсказать глобальные продажи.